package readini

import(
	"strings"
	"io"
	"os"
	"reflect"
	"runtime"
	"time"
	"bufio"
	"errors"
	"fmt"
)
type KeyValue map[string]string
 type Config map[string][]KeyValue

 type ListenFunc func(string)

 type Listener interface  {
	 listen(inifile string)
 }
  var note byte
 func Init(){
	sysType := runtime.GOOS
	if sysType == "linux" {
		note = '#'
	}
	if sysType == "windows" {
		note = ';'
	}
 }

 func ReadFile(filename string)(Config, error){
	Init()
	c := make(Config)
	var err error
	file, err1 := os.Open(filename)
	if err1 != nil {
		err = errors.New("Fail to open file.")
		return c, err
	}
	defer file.Close()
	//listener.listen(filename)
	buf := bufio.NewReader(file)
	section := ""
	//replacer := strings.NewReplacer(" ","")
	for {
		lstr, err2 := buf.ReadString('\n')
		if err2 == io.EOF{
			break
		}
		if err2 != nil {
			err = errors.New("Fail to read file")
			break
		}

		lstr = strings.TrimSpace(lstr)
		if lstr == ""{
			continue
		}
		if lstr[0] == note {
			continue
		}
		length := len(lstr)

		if lstr[0] =='[' && lstr[length - 1] == ']'{
			section = lstr[1: length - 1]
			if _, ok := c[section]; !ok {
				c[section] = []KeyValue{}
			}
		}else {
			s := strings.Split(lstr, "=")
			if len(s) < 2{
				err = errors.New("syntax error: wrong key-value format.")
				break
			}
			key := strings.TrimSpace(s[0])
			value := strings.TrimSpace(s[1])
			keyvalue := make(KeyValue)
			keyvalue[key] = value
			if section == ""{
				c[section] = []KeyValue{}
			}
			if _, ok := c[section]; ok {
				c[section] = append(c[section], keyvalue)
			}
		}
	}
	return c, err
 }
 func (listenfunc ListenFunc) listen(inifile string) {
	config, _ := ReadFile(inifile)
	fmt.Println("listen...")
	for {
		tmpConfig, _ := ReadFile(inifile)

		if !reflect.DeepEqual(config, tmpConfig) {
			break
		}

		time.Sleep(2 * time.Millisecond)
	}
}

func Watch(filename string, listener Listener)(Config, error){
	config, err := ReadFile(filename)
	 
	if err != nil{
		fmt.Printf("error: %s\n", err)
	}
	//var str []string
	fmt.Printf("Before:\n")
	for s, _ := range config {
		for _, value := range config[s] {
			//str = append(str, s)
			fmt.Printf("%s\n",s)
			for k, v := range value {
				fmt.Printf("%s %s\n",k,v)
				//str = append(str, k)
				//str = append(str, v)
			}
		}
	}
	fmt.Printf("\n")
	listener.listen(filename)

	fmt.Printf("file changed\n")
	config, err = ReadFile(filename)
	fmt.Printf("After:\n")
	for s, _ := range config {
		for _, value := range config[s] {
			//str = append(str, s)
			fmt.Printf("%s\n",s)
			for k, v := range value {
				fmt.Printf("%s %s\n",k,v)
				//str = append(str, k)
				//str = append(str, v)
			}
		}
	}
	fmt.Printf("\n")
	return config, err
}

